home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 63 / applic / spell13.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1986-10-16  |  22.0 KB  |  976 lines

  1. program spell;
  2.  
  3. const
  4.   {$i gemconst}
  5.  
  6.   { length of largest possible word }
  7.   max_word_length    =             30;
  8.  
  9.   { number of entries in the hash table }
  10.   table_size         =            1000;
  11.  
  12.   small_length       =               4;
  13.   medium_length      =               8;
  14.   large_length       =              10;
  15.   largest_length     = max_word_length;
  16.   name_of_dictionary =     'words.txt';
  17.   temp_dict_name     =     'words.xxx';
  18.  
  19.   { Color of text }
  20.   color              =           $1180;
  21.  
  22. type
  23.   {$i gemtype}
  24.  
  25.   word_string      = string[max_word_length];
  26.   string_index     = 1..max_word_length;
  27.   hash_index       = 1..table_size;
  28.  
  29.   length_type      = (small, medium, large, largest);
  30.  
  31.   small_string     = string[small_length];
  32.   medium_string    = string[medium_length];
  33.   large_string     = string[large_length];
  34.   largest_string   = string[largest_length];
  35.  
  36.   { pointer to a small, medium, large, or largest string }
  37.   word_pointer     = record
  38.  
  39.                        case tag_field : length_type of
  40.  
  41.                          small   : (small_ptr   : ^small_string);
  42.                          medium  : (medium_ptr  : ^medium_string);
  43.                          large   : (large_ptr   : ^large_string);
  44.                          largest : (largest_ptr : ^largest_string);
  45.  
  46.                      end;
  47.  
  48.   list             = ^cell;
  49.  
  50.   cell             = record
  51.  
  52.                          word : word_pointer;
  53.                          next : list;
  54.  
  55.                        end;
  56.  
  57.   hash_table       = array[hash_index] of list;
  58.  
  59.   word_list        = record
  60.  
  61.                        words   : hash_table;
  62.                        changed : boolean;
  63.  
  64.                      end;
  65.  
  66.   char_file        = packed file of char;
  67.  
  68. var
  69.   { memory-resident dictionary }
  70.   dictionary,
  71.  
  72.   {
  73.   list of words that are spelled correctly but will not be inserted into
  74.   a dictionary.
  75.   }
  76.   secondary_dict   : word_list;
  77.  
  78.   done,
  79.   cancel,
  80.   out_of_memory    : boolean;
  81.   word             : word_string;
  82.   in_file_name,
  83.   out_file_name,
  84.   in_file_type     : string;
  85.   spell_file,
  86.   spelled_file,
  87.   new_spelled_file : char_file;
  88.   next_char        : char;
  89.   button           : integer;
  90.  
  91.  
  92. {$i gemsubs}
  93.  
  94.  
  95. procedure io_check(switch : boolean); external;
  96. function io_result : integer; external;
  97.  
  98.  
  99. function file_exists(filename : string) : boolean;
  100.  
  101. {
  102. Return true if the file specified by filename exists on the default disk.
  103. }
  104.  
  105. const
  106.   { File operation was successfull }
  107.   no_error = 0;
  108.  
  109. var
  110.   input_file : char_file;
  111.  
  112. begin
  113.  
  114.   { Turn off i/o checking. }
  115.   io_check(false);
  116.  
  117.   { Attempt to open the named file. }
  118.   reset(input_file, filename);
  119.  
  120.   { If there was no error opening the file, it is assumed to exist. }
  121.   file_exists := io_result = no_error;
  122.  
  123.   close(input_file);
  124.  
  125.   { Turn i/o checking back on. }
  126.   io_check(true);
  127.  
  128. end;
  129.  
  130.  
  131. procedure remove_white(var str : string);
  132.  
  133. {
  134. Remove all whitespace characters from a character string.  Whitespace
  135. characters are assumed to have character codes less than or equal to
  136. the code for space (' ').
  137. }
  138.  
  139. var
  140.   new_string : string;
  141.   index      : integer;
  142.  
  143. begin
  144.  
  145.   new_string := '';
  146.  
  147.   for index := 1 to length(str) do
  148.     if str[index] > ' '
  149.       then new_string := concat(new_string, str[index]);
  150.  
  151.   str := new_string;
  152.  
  153. end;
  154.  
  155.  
  156. procedure read_char(var input_file : char_file; var ch : char);
  157.  
  158. {
  159. Read a character from a file.
  160. }
  161.  
  162. begin
  163.  
  164.   ch := input_file^;
  165.   get(input_file);
  166.  
  167. end;
  168.  
  169.  
  170. procedure write_char(var output_file : char_file; ch : char);
  171.  
  172. {
  173. Write a character to a file.
  174. }
  175.  
  176. begin
  177.  
  178.   output_file^ := ch;
  179.   put(output_file);
  180.  
  181. end;
  182.  
  183.  
  184. procedure write_word(var output_file : char_file; word : word_string);
  185.  
  186. {
  187. Write a character string to a file.
  188. }
  189.  
  190. var
  191.   index : string_index;
  192.  
  193. begin
  194.  
  195.   for index := 1 to length(word) do
  196.     write_char(output_file, word[index]);
  197.  
  198. end;
  199.  
  200.  
  201. procedure get_word(var input_file, output_file : char_file;
  202.              var word : word_string; var next_char : char);
  203.  
  204. {
  205. Retrieve the next word from the input file.  When the file is completely read,
  206. (word) will be the empty string.
  207. }
  208.  
  209. var
  210.   ch         : char;
  211.   letters,
  212.   apostrophe : set of char;
  213.  
  214. begin
  215.  
  216.   word := '';
  217.  
  218.   letters := ['a'..'z', 'A'..'Z'];
  219.   apostrophe := [''''];
  220.  
  221.   if not eof(input_file)
  222.     then begin
  223.  
  224.       { Get the initial letter of the word. }
  225.       repeat
  226.  
  227.         read_char(input_file, ch);
  228.  
  229.         { Send all letters not in the word to the output file. }
  230.         if not (ch in letters)
  231.           then write_char(output_file, ch);
  232.  
  233.       until (ch in letters) or eof(input_file);
  234.  
  235.       { If the initial letter of the word was found, get the other letters. }
  236.       if ch in letters
  237.         then begin
  238.  
  239.           word := ch;
  240.  
  241.           repeat
  242.  
  243.             read_char(input_file, ch);
  244.  
  245.             if ch in letters + apostrophe
  246.               then word := concat(word, ch)
  247.               else { Save character following word to write to output file. }
  248.                 next_char := ch;
  249.  
  250.           until (not (ch in letters + apostrophe)) or eof(input_file) or
  251.                 (length(word) = max_word_length);
  252.  
  253.         end;
  254.  
  255.     end;
  256.  
  257. end;
  258.  
  259.  
  260. function min(a, b : integer) : integer;
  261.  
  262. {
  263. Return the smaller of a and b.
  264. }
  265.  
  266. begin
  267.  
  268.   if a < b
  269.     then min := a
  270.     else min := b;
  271.  
  272. end;
  273.  
  274.  
  275. function capital(ch : char) : char;
  276.  
  277. {
  278. Return the capital of a lowercase letter.  Return the original
  279. letter otherwise.
  280. }
  281.  
  282. begin
  283.  
  284.   if ch in ['a'..'z']
  285.     then capital := chr(ord(ch) - (ord('a') - ord('A')))
  286.     else capital := ch;
  287.  
  288. end;
  289.  
  290.  
  291. function hash(word : word_string) : hash_index;
  292.  
  293. {
  294. Return an index into the hash table based on a key (word).
  295. }
  296.  
  297. var
  298.   index       : string_index;
  299.   number      : long_integer;
  300.   power_of_10 : integer;
  301.  
  302. begin
  303.  
  304.   { Convert the key to a number. }
  305.   number := 0;
  306.   power_of_10 := 1;
  307.  
  308.   for index := min(4, length(word)) downto 1 do begin
  309.  
  310.     number := number + power_of_10 * ord(capital(word[index]));
  311.     power_of_10 := power_of_10 * 10;
  312.  
  313.   end;
  314.  
  315.   { Compute a valid hash index. }
  316.   hash := int(number mod table_size) + 1;
  317.  
  318. end;
  319.  
  320.  
  321. procedure get_word_from_dictionary(var word : word_string;
  322.                                         word_cell : list);
  323.  
  324. {
  325. Retrieve a word from a cell of the hash table.
  326. }
  327.  
  328. begin
  329.  
  330.   case word_cell^.word.tag_field of
  331.  
  332.     small   : word := word_cell^.word.small_ptr^;
  333.     medium  : word := word_cell^.word.medium_ptr^;
  334.     large   : word := word_cell^.word.large_ptr^;
  335.     largest : word := word_cell^.word.largest_ptr^;
  336.  
  337.   end;
  338.  
  339. end;
  340.  
  341.  
  342. procedure word_capitalize(var word : word_string);
  343.  
  344. {
  345. Make all alphabetic characters of a word upper-case.
  346. }
  347.  
  348. var
  349.   index : string_index;
  350.  
  351. begin
  352.  
  353.   for index := 1 to length(word) do
  354.     word[index] := capital(word[index]);
  355.  
  356. end;
  357.  
  358.  
  359. function words_equal(word_1, word_2 : word_string) : boolean;
  360.  
  361. {
  362. Return true if two words are equal (alphabetic case of characters is
  363. ignored.
  364. }
  365.  
  366. begin
  367.  
  368.   if length(word_1) <> length(word_2)
  369.     then words_equal := false
  370.     else begin
  371.  
  372.       word_capitalize(word_1);
  373.       word_capitalize(word_2);
  374.  
  375.       words_equal := word_1 = word_2;
  376.  
  377.     end;
  378.  
  379. end;
  380.  
  381.  
  382. function word_in_dictionary(word : word_string; dictionary : word_list) :
  383.                                                                  boolean;
  384.  
  385. {
  386. Return true when a word is found in the dictionary.
  387. }
  388.  
  389. var
  390.   index          : hash_index;
  391.   retrieved_word : word_string;
  392.   word_found     : boolean;
  393.  
  394. begin
  395.  
  396.   index := hash(word);
  397.  
  398.   { Single letters will be considered valid words. }
  399.   word_found := length(word) = 1;
  400.  
  401.   { Search for the word in the hash table. }
  402.   while (dictionary.words[index] <> nil) and (not word_found) do begin
  403.  
  404.     get_word_from_dictionary(retrieved_word, dictionary.words[index]);
  405.     word_found := words_equal(word, retrieved_word);
  406.  
  407.     dictionary.words[index] := dictionary.words[index]^.next;
  408.  
  409.   end;
  410.  
  411.   word_in_dictionary := word_found;
  412.  
  413. end;
  414.  
  415.  
  416. procedure insert_word(word : word_string; var dictionary : word_list;
  417.                                         var out_of_memory : boolean);
  418.  
  419. {
  420. Insert a word into the dictionary if it is not already there.
  421. }
  422.  
  423. const
  424.   min_free_memory = 1024;
  425.  
  426. var
  427.   index     : hash_index;
  428.   word_cell : word_pointer;
  429.   new_cell  : list;
  430.  
  431.  
  432.   procedure get_word_cell(word : word_string; var word_cell : word_pointer);
  433.  
  434.   {
  435.   Return a pointer to a word.
  436.   }
  437.  
  438.   begin
  439.  
  440.     {
  441.     Depending on the length of the word, allocate the proper amount of
  442.     memory.
  443.     }
  444.  
  445.     if length(word) in [1..small_length]
  446.       then begin
  447.  
  448.         word_cell.tag_field := small;
  449.         new(word_cell.small_ptr);
  450.         word_cell.small_ptr^ := word;
  451.  
  452.       end;
  453.  
  454.     if length(word) in [small_length + 1 .. medium_length]
  455.       then begin
  456.  
  457.         word_cell.tag_field := medium;
  458.         new(word_cell.medium_ptr);
  459.         word_cell.medium_ptr^ := word;
  460.  
  461.       end;
  462.  
  463.     if length(word) in [medium_length + 1 .. large_length]
  464.       then begin
  465.  
  466.         word_cell.tag_field := large;
  467.         new(word_cell.large_ptr);
  468.         word_cell.large_ptr^ := word;
  469.  
  470.       end;
  471.  
  472.     if length(word) in [large_length + 1 .. largest_length]
  473.       then begin
  474.  
  475.         word_cell.tag_field := largest;
  476.         new(word_cell.largest_ptr);
  477.         word_cell.largest_ptr^ := word;
  478.  
  479.       end;
  480.  
  481.   end;
  482.  
  483.  
  484. begin
  485.  
  486.   { Find out if memory is getting low. }
  487.   out_of_memory := memavail < min_free_memory;
  488.  
  489.   if (not out_of_memory) and (not word_in_dictionary(word, dictionary)) and
  490.      (length(word) in [1..largest_length])
  491.     then begin
  492.  
  493.       { Get a pointer to a cell containing the word. }
  494.       get_word_cell(word, word_cell);
  495.  
  496.       { Insert the word into the hash table. }
  497.       new(new_cell);
  498.       new_cell^.word := word_cell;
  499.  
  500.       index := hash(word);
  501.  
  502.       new_cell^.next := dictionary.words[index];
  503.       dictionary.words[index] := new_cell;
  504.  
  505.     end;
  506.  
  507. end;
  508.  
  509.  
  510. procedure clear_dictionary(var dictionary : word_list);
  511.  
  512. {
  513. Initialize the dictionary to empty.
  514. }
  515.  
  516. var
  517.   index : hash_index;
  518.  
  519. begin
  520.  
  521.   for index := 1 to table_size do
  522.     dictionary.words[index] := nil;
  523.  
  524.   dictionary.changed := false;
  525.  
  526. end;
  527.  
  528.  
  529. procedure load_dictionary(var dictionary : word_list;
  530.                         var out_of_memory : boolean);
  531.  
  532. {
  533. Load the dictionary with words from a disk file.
  534. }
  535.  
  536. var
  537.   word_file : text;
  538.   word      : word_string;
  539.  
  540. begin
  541.  
  542.   { Make mouse a "busy bee". }
  543.   set_mouse(m_bee);
  544.  
  545.   { Load the dictionary into memory. }
  546.  
  547.   { Make the dictionary empty. }
  548.   clear_dictionary(dictionary);
  549.  
  550.   { If the dictionary disk file does not exist, create a new (empty) one. }
  551.   if not file_exists(name_of_dictionary)
  552.     then begin
  553.  
  554.       rewrite(word_file, name_of_dictionary);
  555.       close(word_file);
  556.  
  557.     end;
  558.  
  559.   { Prepare to read words from the disk file. }
  560.   reset(word_file, name_of_dictionary);
  561.  
  562.   out_of_memory := false;
  563.  
  564.   { Insert each word in the disk file into the dictionary. }
  565.  
  566.   while (not eof(word_file)) and (not out_of_memory) do begin
  567.  
  568.     readln(word_file, word);
  569.     insert_word(word, dictionary, out_of_memory);
  570.  
  571.   end;
  572.  
  573.   { Make the mouse an arrow again. }
  574.   set_mouse(m_arrow);
  575.  
  576. end;
  577.  
  578.  
  579. procedure update_dictionary(dictionary : word_list);
  580.  
  581. {
  582. Save all dictionary words in a disk file if the dictionary has changed.
  583. }
  584.  
  585. var
  586.   index         : hash_index;
  587.   word          : word_string;
  588.   word_file,
  589.   new_word_file : text;
  590.   button        : integer;
  591.  
  592. begin
  593.  
  594.   if dictionary.changed
  595.     then begin
  596.  
  597.       { Find out if user wants to update the dictionary stored on disk. }
  598.       button := do_alert('[0][Update Dictionary?][YES|NO]', 1);
  599.  
  600.       if button = 1
  601.         then begin
  602.  
  603.           { Make the mouse a "busy bee." }
  604.           set_mouse(m_bee);
  605.  
  606.           { Save dictionary with a temporary filename. }
  607.           rewrite(word_file, temp_dict_name);
  608.  
  609.           { Save all words stored in each list of the hash table. }
  610.           for index := 1 to table_size do begin
  611.  
  612.             { Save all words stored in current list of the hash table. }
  613.             while dictionary.words[index] <> nil do begin
  614.  
  615.               get_word_from_dictionary(word, dictionary.words[index]);
  616.               writeln(word_file, word);
  617.  
  618.               { Advance to next cell of current list. }
  619.               dictionary.words[index] := dictionary.words[index]^.next;
  620.  
  621.             end;
  622.  
  623.           end;
  624.  
  625.           { Replace old dictionary with new dictionary. }
  626.           rewrite(new_word_file, name_of_dictionary);
  627.           rename(word_file, new_word_file);
  628.  
  629.           { Return mouse to arrow shape. }
  630.           set_mouse(m_arrow);
  631.  
  632.         end;
  633.  
  634.     end;
  635.  
  636. end;
  637.  
  638.  
  639. procedure process_word(var word : word_string; var dictionary,
  640.      secondary_dict : word_list; var out_of_memory : boolean);
  641.  
  642. {
  643. Process a misspelled word: either
  644.  
  645. i.   place word in dictionary
  646. ii.  change spelling of word
  647. iii. don't change word
  648. }
  649.  
  650. var
  651.   insert_wd : boolean;
  652.  
  653.  
  654.   procedure get_option(var word : word_string; var insert_wd : boolean);
  655.  
  656.   {
  657.   Allow user to correct the spelling of a possibly misspelled word and insert
  658.   it into the dictionary.
  659.   }
  660.  
  661.   const
  662.     not_in_dict  = 'is not in the dictionary.';
  663.     question     = 'Add this word to dictionary?';
  664.  
  665.     { Width (in characters) of dialog box }
  666.     box_width    = 40;
  667.  
  668.   var
  669.     word_line,
  670.     line_2,
  671.     line_3,
  672.     button_pushed,
  673.     no_button,
  674.     yes_button     : integer;
  675.     option_box     : dialog_ptr;
  676.     word_string    : str255;
  677.  
  678.   begin
  679.  
  680.     { Get a dialog box. }
  681.     option_box := new_dialog(5, 0, 0, box_width, 7);
  682.  
  683.     { Place possibly misspelled word in the dialog box. }
  684.     word_line := add_ditem(option_box, g_ftext, editable, 1, 1, 30, 1, 0,
  685.                                                                   color);
  686.  
  687.     line_2 := add_ditem(option_box, g_text, none, 1, 2, length(not_in_dict),
  688.                                                                1, 0, color);
  689.  
  690.     line_3 := add_ditem(option_box, g_text, none, 1, 3, length(question),
  691.                                                             1, 0, color);
  692.  
  693.     { Place YES and NO buttons in the dialog box. }
  694.     yes_button := add_ditem(option_box, g_button, exit_btn | selectable, 10, 5,
  695.                                                    length('YES'), 1, 0, color);
  696.  
  697.     no_button := add_ditem(option_box, g_button, exit_btn | selectable,
  698.                                      28, 5, length('NO'), 1, 0, color);
  699.  
  700.     { Prepare to allow user to correct the spelling of the word. }
  701.     set_dedit(option_box, word_line, '______________________________',
  702.                                      'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
  703.                                           word, system_font, te_left);
  704.  
  705.     set_dtext(option_box, line_2, not_in_dict, system_font, te_center);
  706.     set_dtext(option_box, line_3, question, system_font, te_center);
  707.  
  708.     { Prepare to have the YES or NO buttons pressed. }
  709.     set_dtext(option_box, yes_button, 'YES', system_font, te_center);
  710.     set_dtext(option_box, no_button, 'NO', system_font, te_center);
  711.  
  712.     center_dialog(option_box);
  713.  
  714.     { Get user input from dialog box. }
  715.     button_pushed := do_dialog(option_box, word_line);
  716.  
  717.     { Retrieve the possibly edited word. }
  718.     get_dedit(option_box, word_line, word_string);
  719.     word := word_string;
  720.  
  721.     insert_wd := button_pushed = yes_button;
  722.  
  723.     end_dialog(option_box);
  724.     delete_dialog(option_box);
  725.  
  726.   end;
  727.  
  728.  
  729. begin
  730.  
  731.   {
  732.   Allow user to correct spelling of word, and have him decide if it
  733.   will be inserted into the dictionary.
  734.   }
  735.  
  736.   get_option(word, insert_wd);
  737.  
  738.   {
  739.   If the word is to be inserted into the dictionary, do so.  Otherwise
  740.   insert the word into the secondary dictionary so that the user will
  741.   not be asked about the word a second time.
  742.   }
  743.   if insert_wd
  744.     then begin
  745.  
  746.       insert_word(word, dictionary, out_of_memory);
  747.       dictionary.changed := true;
  748.  
  749.     end
  750.     else insert_word(word, secondary_dict, out_of_memory);
  751.  
  752. end;
  753.  
  754.  
  755. procedure get_input_filename(var in_file_name, in_file_type : string;
  756.                                                var cancel : boolean);
  757.  
  758. {
  759. Get the name the file to be corrected.  If cancel is true after this
  760. procedure is called, the program is exited.
  761. }
  762.  
  763. const
  764.   fl_type_length = 3;
  765.  
  766. var
  767.   button   : integer;
  768.   path,
  769.   filename : string;
  770.  
  771. begin
  772.  
  773.   { Default path for filename selection }
  774.   path := 'A:\*.DOC';
  775.  
  776.   {
  777.   Place file selection box on screen and allow user to choose a file or
  778.   to press the cancel button.  Repeat until user enters a valid filename
  779.   or presses the cancel button.
  780.   }
  781.  
  782.   repeat
  783.  
  784.     cancel := not get_in_file(path, filename);
  785.  
  786.     {
  787.     If the requested file does not exist, have the user choose an existing
  788.     file or quit the program.
  789.     }
  790.  
  791.     if (not cancel) and (not file_exists(filename))
  792.       then begin
  793.  
  794.         button := do_alert('[2][Not found-Try again?][YES|NO]', 1);
  795.         cancel := button = 2;
  796.  
  797.       end;
  798.  
  799.   until cancel or file_exists(filename);
  800.  
  801.   {
  802.   If the filename of an existing filename has been given, extract
  803.   the name and type of the file.
  804.   }
  805.  
  806.   if not cancel
  807.     then begin
  808.  
  809.       if pos('.', filename) <> 0
  810.         then begin
  811.  
  812.           in_file_type := copy(filename, pos('.', filename) + 1,
  813.                          length(filename) - pos('.', filename));
  814.           in_file_name := copy(filename, 1, pos('.', filename) - 1);
  815.  
  816.         end
  817.         else begin
  818.  
  819.           in_file_type := '';
  820.           in_file_name := filename;
  821.  
  822.         end;
  823.  
  824.       remove_white(in_file_name);
  825.       remove_white(in_file_type);
  826.  
  827.     end;
  828.  
  829. end;
  830.  
  831.  
  832. procedure introduce_program;
  833.  
  834. {
  835. Introduce the program with a dialog box.
  836. }
  837.  
  838. const
  839.   { Width (in characters) of dialog box }
  840.   box_width = 64;
  841.  
  842.   { Strings that will be inserted into dialog box. }
  843.   str_1     = 'Spell 1.3 - A Spelling Correction Program';
  844.   str_2     = 'Written by Eric Bergman-Terrell';
  845.   str_3     = 'of Cadenza Software, Ltd.';
  846.   str_4     = '1704 Imperial Ridge, Las Cruces, NM  88001, USA';
  847.   str_5     = 'Portions of this product are copyright (c) 1986, OSS and CCD';
  848.   str_6     = 'Used by Permission of OSS';
  849.   str_7     = 'This software has been placed in the public domain.';
  850.   start_str = 'BEGIN';
  851.  
  852. var
  853.   intro_box     : dialog_ptr;
  854.   line_1,
  855.   line_2,
  856.   line_3,
  857.   line_4,
  858.   line_5,
  859.   line_6,
  860.   line_7,
  861.   start_button,
  862.   button_pushed : integer;
  863.   start_item    : tree_index;
  864.  
  865. begin
  866.  
  867.   { Set up the mouse the be an arrow. }
  868.   init_mouse;
  869.   set_mouse(m_arrow);
  870.  
  871.   { Get a dialog box. }
  872.   intro_box := new_dialog(8, 0, 0, box_width, 16);
  873.  
  874.   { Insert strings into dialog box. }
  875.   line_1 := add_ditem(intro_box, g_text, none, 1, 1, box_width, 1, 0, color);
  876.   line_2 := add_ditem(intro_box, g_text, none, 1, 3, box_width, 1, 0, color);
  877.   line_3 := add_ditem(intro_box, g_text, none, 1, 4, box_width, 1, 0, color);
  878.   line_4 := add_ditem(intro_box, g_text, none, 1, 5, box_width, 1, 0, color);
  879.   line_5 := add_ditem(intro_box, g_text, none, 1, 7, box_width, 1, 0, color);
  880.   line_6 := add_ditem(intro_box, g_text, none, 1, 8, box_width, 1, 0, color);
  881.   line_7 := add_ditem(intro_box, g_text, none, 1, 11, box_width, 1, 0, color);
  882.   start_button := add_ditem(intro_box, g_button,
  883.                             exit_btn | selectable | default,
  884.                             30, 14, length(start_str), 1, 0, color);
  885.  
  886.   { Adjust the strings in the dialog box. }
  887.   set_dtext(intro_box, line_1, str_1, system_font, te_center);
  888.   set_dtext(intro_box, line_2, str_2, system_font, te_center);
  889.   set_dtext(intro_box, line_3, str_3, system_font, te_center);
  890.   set_dtext(intro_box, line_4, str_4, system_font, te_center);
  891.   set_dtext(intro_box, line_5, str_5, system_font, te_center);
  892.   set_dtext(intro_box, line_6, str_6, system_font, te_center);
  893.   set_dtext(intro_box, line_7, str_7, system_font, te_center);
  894.   set_dtext(intro_box, start_button, start_str, system_font, te_center);
  895.  
  896.   center_dialog(intro_box);
  897.  
  898.   { Introduce the program. }
  899.   button_pushed := do_dialog(intro_box, start_item);
  900.  
  901.   end_dialog(intro_box);
  902.   delete_dialog(intro_box);
  903.  
  904. end;
  905.  
  906.  
  907. begin
  908.  
  909.   if init_gem >= 0
  910.     then begin
  911.  
  912.       introduce_program;
  913.  
  914.       load_dictionary(dictionary, out_of_memory);
  915.  
  916.       {
  917.       Initialize list of correctly spelled words that will not be
  918.       inserted into a dictionary.
  919.       }
  920.       clear_dictionary(secondary_dict);
  921.  
  922.       if not out_of_memory
  923.         then begin
  924.  
  925.           get_input_filename(in_file_name, in_file_type, cancel);
  926.  
  927.           if not cancel
  928.             then begin
  929.  
  930.               out_file_name := concat(in_file_name, '.XXX');
  931.  
  932.               reset(spell_file, concat(in_file_name, '.', in_file_type));
  933.               rewrite(spelled_file, out_file_name);
  934.  
  935.               repeat
  936.  
  937.                 get_word(spell_file, spelled_file, word, next_char);
  938.  
  939.                 done := length(word) = 0;
  940.  
  941.                 if not done
  942.                   then begin
  943.  
  944.                     if (not word_in_dictionary(word, dictionary)) and
  945.                        (not word_in_dictionary(word, secondary_dict))
  946.                       then process_word(word, dictionary, secondary_dict,
  947.                                                           out_of_memory);
  948.  
  949.                     write_word(spelled_file, word);
  950.                     write_char(spelled_file, next_char);
  951.  
  952.                 end;
  953.  
  954.               until done or out_of_memory;
  955.  
  956.               close(spell_file);
  957.  
  958.               { Replace old input file with file that has been corrected. }
  959.               rewrite(new_spelled_file, concat(in_file_name, '.',
  960.                                                   in_file_type));
  961.               rename(spelled_file, new_spelled_file);
  962.  
  963.               { Update dictionary if it has changed. }
  964.               update_dictionary(dictionary);
  965.  
  966.             end;
  967.  
  968.         end;
  969.  
  970.       if out_of_memory
  971.         then button := do_alert('[1][Out of Memory][CANCEL]', 1);
  972.  
  973.     end;
  974.  
  975. end.
  976.